package com.socket.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author wangg
 * @date 2019/4/9 13:47
 * 采用线程池和任务队列可以实现一种伪异步IO通信框架。在学习过连接池和队列的使用，
 * 我们将客户端的socket封装成一个task任务（实现Runnable接口的类）然后投递到线程池中去，
 * 配置相应的队列进行实现
 */
class ABSocketServce {
    private final int PORT;
    private static ThreadFactory tFactory = r -> {
        Thread thread = new Thread(r);
        thread.setName("BsocketServer_" + thread.getId());
        return thread;
    };
    private static ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 100, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), tFactory);

    ABSocketServce(int port) {
        PORT = port;
    }

    static {
        executor.allowCoreThreadTimeOut(true);
    }
    public void execute() {
        ServerSocket server = null;

        try {
            server = new ServerSocket(this.PORT);
            System.out.println(" blocked Socket start...");
            while (true) {
                Socket socket = null;
                try {
                    socket = server.accept();
                    executor.execute(new ABSocketThread(socket));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (server != null) {
                try {
                    server.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class ABSocketThread implements Runnable{
        private  Socket socket;

        ABSocketThread(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                String rec = new BaseReceive(socket).execute();
                String rep = new BaseReply(socket.getOutputStream()).execute(String.format("%s 我接受的你的信息了:{%s}", sdf.format(new Date()), rec));
                System.out.println("我发送的信息：" + rep);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

}